using UniversalAdmin.Application.Dto;
using UniversalAdmin.Application.Commands;
using UniversalAdmin.Domain.Entities.App;
using UniversalAdmin.Domain.Repositories;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
using UniversalAdmin.Shared.Enums;
using UniversalAdmin.Infrastructure.Data.Contexts;
using Microsoft.EntityFrameworkCore;

namespace UniversalAdmin.Application.Services;

public partial class AppRoleServices : IAppRoleServices
{
    private readonly IRepository<AppRole> _roleRepository;
    private readonly IRepository<AppPermission> _permissionRepository;
    private readonly AdminDbContext _db;
    public AppRoleServices(IRepository<AppRole> roleRepository, IRepository<AppPermission> permissionRepository, AdminDbContext db)
    {
        _roleRepository = roleRepository;
        _permissionRepository = permissionRepository;
        _db = db;
    }

    public async Task<ApiResult> CreateAsync(CreateRoleDto dto)
    {
        if (_roleRepository.All.Any(r =>
            r.RoleName.ToLower() == dto.RoleName.ToLower() &&
            (r.Description == null || !r.Description.StartsWith("[已删除]"))))
        {
            return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "角色名已存在");
        }
        var role = new AppRole
        {
            Id = Guid.NewGuid(),
            RoleName = dto.RoleName,
            Description = dto.Description
        };
        await _roleRepository.CreatedAsync(role);
        return ApiResult.Success((int)ApiStatusCode.SUCCESS, "创建角色成功");
    }

    public async Task<ApiResult> UpdateRoleAsync(Guid id, UpdateRoleDto dto)
    {
        var role = await _roleRepository.GetByIdAsync(id);
        if (role == null) return ApiResult.Failed(404, "角色不存在");
        if (_roleRepository.Table.Any(r => r.RoleName == dto.RoleName && r.Id != id))
            return ApiResult.Failed(400, "角色名已存在");
        role.RoleName = dto.RoleName;
        role.Description = dto.Description;
        await _roleRepository.UpdateAsync(role);
        return ApiResult.Success("更新角色成功");
    }

    public async Task<ApiResult> DeleteRoleAsync(Guid id)
    {
        var role = await _roleRepository.GetByIdAsync(id);
        if (role == null) return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "角色不存在");
        if (role.IsDelete) return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "角色已被删除");
        role.IsDelete = true;
        await _roleRepository.UpdateAsync(role);
        return ApiResult.Success((int)ApiStatusCode.SUCCESS, "删除角色成功");
    }

    public async Task<ApiResult> EnableRole(Guid id)
    {
        var role = await _roleRepository.GetByIdAsync(id);
        if (role == null) return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "角色不存在");
        if (role.IsDelete) return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "角色已被删除，请确认后重试");
        if (role.IsActive) return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "角色已是启用状态");
        role.IsActive = true;
        await _roleRepository.UpdateAsync(role);
        return ApiResult.Success((int)ApiStatusCode.SUCCESS, "启用角色成功");
    }

    public async Task<ApiResult> DisableRole(Guid id)
    {
        var role = await _roleRepository.GetByIdAsync(id);
        if (role == null) return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "角色不存在");
        if (role.IsDelete) return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "角色已被删除，请确认后重试");
        if (!role.IsActive) return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "角色已是禁用状态");
        role.IsActive = false;
        await _roleRepository.UpdateAsync(role);
        return ApiResult.Success((int)ApiStatusCode.SUCCESS, "禁用角色成功");
    }

    public async Task<ApiResult> AssignPermission(Guid roleId, string permissionCode)
    {
        var role = await _roleRepository.GetByIdAsync(roleId);
        if (role == null) return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "角色不存在");
        if (role.IsDelete) return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "角色已被删除");
        var permission = _permissionRepository.All.FirstOrDefault(p => p.PermissionCode == permissionCode);
        if (permission == null) return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "权限不存在");
        if (role.Permissions.Any(p => p.Id == permission.Id))
            return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "该权限已分配给该角色");
        // 用EF导航属性插入关联表
        role.Permissions.Add(permission);
        await _roleRepository.UpdateAsync(role);
        return ApiResult.Success((int)ApiStatusCode.SUCCESS, "分配权限成功");
    }

    public async Task<ApiResult> AssignPermissions(Guid roleId, List<string> permissionCodes)
    {
        var role = await _roleRepository.GetByIdAsync(roleId);
        if (role == null) return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "角色不存在");
        if (role.IsDelete) return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "角色已被删除");

        var permissions = _permissionRepository.All
            .Where(p => permissionCodes.Contains(p.PermissionCode))
            .ToList();

        if (permissions.Count != permissionCodes.Count)
            return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "部分权限不存在");

        // 清空原有权限（如需追加请去掉此行）
        role.Permissions.Clear();
        foreach (var perm in permissions)
            role.Permissions.Add(perm);

        await _roleRepository.UpdateAsync(role);
        return ApiResult.Success((int)ApiStatusCode.SUCCESS, "分配权限成功");
    }

    public async Task<ApiResult> AssignPermissions(Guid roleId, List<Guid> permissionIds)
    {
        var role = await _db.AppRoles.Include(r => r.Permissions).FirstOrDefaultAsync(r => r.Id == roleId);
        if (role == null) return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "角色不存在");
        if (role.IsDelete) return ApiResult.Failed((int)ApiStatusCode.CONFLICT, "角色已被删除");

        var distinctIds = permissionIds.Distinct().ToList();
        var permissions = _db.AppPermissions.Where(p => distinctIds.Contains(p.Id)).ToList();
        if (permissions.Count != distinctIds.Count)
            return ApiResult.Failed((int)ApiStatusCode.NOT_FOUND, "部分权限不存在");

        // 先清空
        role.Permissions.Clear();
        await _db.SaveChangesAsync(); // 先保存一次，确保数据库已删除所有关联

        // 再分配
        foreach (var perm in permissions)
            role.Permissions.Add(perm);

        await _db.SaveChangesAsync();
        return ApiResult.Success((int)ApiStatusCode.SUCCESS, "分配权限成功");
    }

    public async Task<ApiResult<PagedResult<RoleDto>>> GetPagedAsync(PagedQuery query)
    {
        var q = _db.AppRoles.Where(r => !r.IsDelete);
        if (!string.IsNullOrWhiteSpace(query.Search))
            q = q.Where(r => r.RoleName.Contains(query.Search) || (r.Description ?? "").Contains(query.Search));
        var total = await q.CountAsync();
        var items = await q.OrderByDescending(r => r.CreatedAt)
            .ThenBy(r => r.Id)
            .Skip((query.Page - 1) * query.Size)
            .Take(query.Size)
            .Select(r => new RoleDto
            {
                Id = r.Id,
                RoleName = r.RoleName,
                Description = r.Description,
                IsActive = r.IsActive
            })
            .ToListAsync();
        return ApiResult<PagedResult<RoleDto>>.Success(200, "操作成功", new PagedResult<RoleDto>(items, total, query.Page, query.Size));
    }

    public async Task<ApiResult<IEnumerable<RoleDto>>> GetAllAsync(string? search = null)
    {
        var q = _db.AppRoles.Where(r => !r.IsDelete);
        if (!string.IsNullOrWhiteSpace(search))
            q = q.Where(r => r.RoleName.Contains(search) || (r.Description ?? "").Contains(search));
        var items = await q.OrderByDescending(r => r.CreatedAt)
            .ThenBy(r => r.Id)
            .Select(r => new RoleDto
            {
                Id = r.Id,
                RoleName = r.RoleName,
                Description = r.Description,
                IsActive = r.IsActive
            })
            .ToListAsync();
        return ApiResult<IEnumerable<RoleDto>>.Success(200, "操作成功", items.AsEnumerable());
    }

    public async Task<RoleDto> GetByRoleId(Guid id)
    {
        var role = await _roleRepository.GetByIdAsync(id);
        if (role == null) return null;
        return new RoleDto { Id = role.Id, RoleName = role.RoleName, Description = role.Description, IsActive = role.IsActive };
    }

    public async Task<ApiResult<RoleDto>> GetByIdAsync(Guid id)
    {
        var role = await _roleRepository.GetByIdAsync(id);
        if (role == null) return ApiResult<RoleDto>.Failed("角色不存在", (int)ApiStatusCode.NOT_FOUND);
        return ApiResult<RoleDto>.Success((int)ApiStatusCode.SUCCESS, "操作成功", new RoleDto { Id = role.Id, RoleName = role.RoleName, Description = role.Description, IsActive = role.IsActive });
    }

    public async Task<ApiResult> UpdateAsync(Guid id, UpdateRoleDto dto) => await UpdateRoleAsync(id, dto);
    public async Task<ApiResult> DeleteAsync(Guid id) => await DeleteRoleAsync(id);
}